home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Software of the Month Club 2000 October
/
Software of the Month - Ultimate Collection Shareware 277.iso
/
pc
/
PROGRAMS
/
UTILITY
/
WINLINUX
/
DATA1.CAB
/
programs_-_kernel_source
/
KERNEL
/
RESOURCE.C
< prev
next >
Wrap
C/C++ Source or Header
|
1999-09-17
|
4KB
|
190 lines
/*
* linux/kernel/resource.c
*
* Copyright (C) 1995 Linus Torvalds
* David Hinds
*
* Kernel io-region resource management
*/
#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/ioport.h>
#include <linux/init.h>
#define IOTABLE_SIZE 128
typedef struct resource_entry_t {
u_long from, num;
const char *name;
struct resource_entry_t *next;
} resource_entry_t;
static resource_entry_t iolist = { 0, 0, "", NULL };
static resource_entry_t iotable[IOTABLE_SIZE];
/*
* This generates the report for /proc/ioports
*/
int get_ioport_list(char *buf)
{
resource_entry_t *p;
int len = 0;
for (p = iolist.next; (p) && (len < 4000); p = p->next)
len += sprintf(buf+len, "%04lx-%04lx : %s\n",
p->from, p->from+p->num-1, p->name);
if (p)
len += sprintf(buf+len, "4K limit reached!\n");
return len;
}
/*
* The workhorse function: find where to put a new entry
*/
static resource_entry_t *find_gap(resource_entry_t *root,
u_long from, u_long num)
{
unsigned long flags;
resource_entry_t *p;
if (from > from+num-1)
return NULL;
save_flags(flags);
cli();
for (p = root; ; p = p->next) {
if ((p != root) && (p->from+p->num-1 >= from)) {
p = NULL;
break;
}
if ((p->next == NULL) || (p->next->from > from+num-1))
break;
}
restore_flags(flags);
return p;
}
/*
* Call this from the device driver to register the ioport region.
*/
void request_region(unsigned long from, unsigned long num, const char *name)
{
resource_entry_t *p;
int i;
for (i = 0; i < IOTABLE_SIZE; i++)
if (iotable[i].num == 0)
break;
if (i == IOTABLE_SIZE)
printk("warning: ioport table is full\n");
else {
p = find_gap(&iolist, from, num);
if (p == NULL)
return;
iotable[i].name = name;
iotable[i].from = from;
iotable[i].num = num;
iotable[i].next = p->next;
p->next = &iotable[i];
return;
}
}
/*
* Call this when the device driver is unloaded
*/
void release_region(unsigned long from, unsigned long num)
{
resource_entry_t *p, *q;
for (p = &iolist; ; p = q) {
q = p->next;
if (q == NULL)
break;
if ((q->from == from) && (q->num == num)) {
q->num = 0;
p->next = q->next;
return;
}
}
}
/*
* Call this to check the ioport region before probing
*/
int check_region(unsigned long from, unsigned long num)
{
return (find_gap(&iolist, from, num) == NULL) ? -EBUSY : 0;
}
#ifdef __sparc__ /* Why to carry unused code on other architectures? */
/*
* This is for architectures with MMU-managed ports (sparc).
*/
unsigned long occupy_region(unsigned long base, unsigned long end,
unsigned long num, unsigned int align, const char *name)
{
unsigned long from = 0, till;
unsigned long flags;
int i;
resource_entry_t *p; /* Scanning ptr */
resource_entry_t *p1; /* === p->next */
resource_entry_t *s; /* Found slot */
if (base > end-1)
return 0;
if (num > end - base)
return 0;
for (i = 0; i < IOTABLE_SIZE; i++)
if (iotable[i].num == 0)
break;
if (i == IOTABLE_SIZE) {
/* Driver prints a warning typically. */
return 0;
}
save_flags(flags);
cli();
/* printk("occupy: search in %08lx[%08lx] ", base, end - base); */
s = NULL;
for (p = &iolist; p != NULL; p = p1) {
p1 = p->next;
/* Find window in list */
from = (p->from+p->num + align-1) & ~((unsigned long)align-1);
till = (p1 == NULL)? (unsigned long) (0 - (unsigned long)align): p1->from;
/* printk(" %08lx:%08lx", from, till); */
/* Clip window with base and end */
if (from < base) from = base;
if (till > end) till = end;
/* See if result is large enougth */
if (from < till && from + num < till) {
s = p;
break;
}
}
/* printk("\r\n"); */
restore_flags(flags);
if (s == NULL)
return 0;
iotable[i].name = name;
iotable[i].from = from;
iotable[i].num = num;
iotable[i].next = s->next;
s->next = &iotable[i];
return from;
}
#endif
/* Called from init/main.c to reserve IO ports. */
void __init reserve_setup(char *str, int *ints)
{
int i;
for (i = 1; i < ints[0]; i += 2)
request_region(ints[i], ints[i+1], "reserved");
}